package com.chushouya.order.service.api.impl;

import com.chushouya.order.dto.api.order.*;
import com.general.framework.core.lang.*;
import com.chushouya.common.support.Contexts;
import com.chushouya.common.support.DevOption;
import com.chushouya.common.util.RabbitMQUtil;
import com.general.framework.core.exception.Ex;
import com.general.framework.data.redis.RedisLock;
import com.chushouya.manager.dao.entity.PartnerEntity;
import com.chushouya.manager.dao.entity.RegionEntity;
import com.chushouya.manager.service.common.PartnerApiService;
import com.chushouya.manager.service.common.RegionService;
import com.chushouya.manager.service.common.UserPaymentMethodApiService;
import com.chushouya.order.constants.OrderStatusEnum;
import com.chushouya.order.constants.OrderTypeEnum;
import com.chushouya.order.dao.entity.OrderEntity;
import com.chushouya.order.dao.entity.OrderProductEntity;
import com.chushouya.order.dao.entity.OrderAddressEntity;
import com.chushouya.order.dao.entity.OrderExtendEntity;
import com.chushouya.order.dao.repository.OrderRepository;
import com.chushouya.order.dao.repository.OrderProductRepository;
import com.chushouya.order.dao.repository.OrderAddressRepository;
import com.chushouya.order.dao.repository.OrderExtendRepository;
//=====order.dto.api.order.*;
import com.chushouya.order.dto.mq.promote.PromoteMqDTO;
import com.chushouya.common.constant.RabbitMqQueueEnum;
import com.chushouya.order.rabbitmq.sender.ExpressReservationMessageSender;
import com.chushouya.order.rabbitmq.sender.NotifyMessageSender;
import com.chushouya.order.service.api.OrderSubmitApiService;
import com.chushouya.manager.service.common.ConfigApiService;
import com.chushouya.product.dao.entity.EvaluateLogEntity;
import com.chushouya.product.service.api.EvaluateApiService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

/**
 * 订单提交API服务实现
 */
@Service
@Slf4j
public class OrderSubmitApiServiceImpl implements OrderSubmitApiService {

    @Resource
    private OrderRepository orderRepository;

    @Resource
    private OrderProductRepository orderProductRepository;

    @Resource
    private OrderAddressRepository orderAddressRepository;

    @Resource
    private OrderExtendRepository orderExtendRepository;

    @Resource
    private EvaluateApiService evaluateApiService;

    @Resource
    private PartnerApiService partnerApiService;

    @Resource
    private RegionService regionService;

    @Resource
    private UserPaymentMethodApiService userPaymentMethodApiService;

    @Resource
    private RabbitMQUtil rabbitMQUtil;

    @Resource
    private RedisLock redisLock;

    @Resource
    private NotifyMessageSender notifyMessageSender;

    @Resource
    private ExpressReservationMessageSender expressReservationMessageSender;

    @Resource
    private ConfigApiService configApiService;

    /**
     * 获取估价信息
     * @return
     */
    private EvaluateLogEntity getEvaluate(String evaluateId) {

        EvaluateLogEntity evaluateLog = evaluateApiService.getEvaluateInfo(evaluateId);
        if (Objects.isNull(evaluateLog)) {
            throw Ex.business("估价信息不存在");
        }
        return evaluateLog;
    }

    @Override
    public OrderUserApiDTO submitOrder(OrderSubmitApiDTO dto) {
        // 1. 创建分布式锁，防止重复提交
        final String lockKey = Strings.format("order_submit_lock:{}", dto.getEvaluateId());
        boolean lockAcquired = redisLock.tryLock(lockKey, 5L, TimeUnit.SECONDS);
        if (!lockAcquired) {
            log.error("订单提交过于频繁：{}", Jsons.toJsonString(dto));
            throw Ex.business("操作频繁，请稍后再试");
        }

        try {
            // 2. 获取用户上下文
            Long userId = Contexts.getUserContext().getUserId();
            if (Longs.isNullOrZero(userId)) {
                throw Ex.business("用户未登录");
            }
            OrderUserApiDTO orderUserApiDTO = new OrderUserApiDTO();

            // 3. 验证订单数据
            validateOrderData(dto);

            // 4. 创建订单数据
            OrderEntity orderEntity = createOrderData(dto, userId);
            orderUserApiDTO.setOrderNo(orderEntity.getOrderNo());
            // 6. 执行订单创建后的处理（异步）
            handleOrderAfter(orderEntity, dto);
            return orderUserApiDTO;
        } finally {
            // 只有成功获取锁的情况下才释放锁
            if (lockAcquired) {
                redisLock.unlock(lockKey);
            }
        }
    }

    /**
     * 验证订单数据
     */
    private void validateOrderData(OrderSubmitApiDTO dto) {
        // 验证估价ID
        if (Strings.isEmpty(dto.getEvaluateId())) {
            throw Ex.business("估价ID不能为空");
        }

        // 验证回收方式
        if (Objects.isNull(dto.getOrderType()) || (dto.getOrderType() != 1 && dto.getOrderType() != 2)) {
            throw Ex.business("回收方式无效，必须为1(邮寄)或2(上门)");
        }

        // 验证预约时间
        if (Objects.isNull(dto.getAppointStartTime()) || Objects.isNull(dto.getAppointEndTime())) {
            throw Ex.business("预约时间不能为空");
        }
    }

    /**
     * 创建订单数据
     */
    @Transactional
    public OrderEntity createOrderData(OrderSubmitApiDTO dto, Long userId) {
        final String evaluateId = dto.getEvaluateId();
        final Long partnerId = Contexts.getHeaderContext().getPartnerId();
        log.info("提交订单，估价ID：{}，用户ID：{}，合作商ID：{}", evaluateId, userId, Contexts.getHeaderContext());
        final String platform = Contexts.getHeaderContext().getPlatform();
        final String channel = dto.getChannel();

        EvaluateLogEntity evaluateLog = getEvaluate(evaluateId);
        PartnerEntity partnerEntity = getPartnerInfo(partnerId);
        
        log.info("开始创建订单，估价ID：{}", dto.getEvaluateId());

        // 2. 生成系统订单号
        String orderNo = generateOrderNo();

        final OrderAddressApiDTO orderAddressApiDTO = dto.getAddressInfo();
        final String userName = orderAddressApiDTO.getUserName();
        final String userPhone = orderAddressApiDTO.getUserPhone();

        // 3. 创建订单实体
        OrderEntity orderEntity = new OrderEntity();
        orderEntity.setOrderNo(orderNo);
        orderEntity.setUserId(userId);
        orderEntity.setUserName(userName);
        orderEntity.setUserPhone(userPhone);
        orderEntity.setProductId(evaluateLog.getProductId());
        orderEntity.setProductName(evaluateLog.getProductName());
        orderEntity.setProductImage(evaluateLog.getProductImage());
        
        // 设置订单状态和类型
        orderEntity.setOrderStatus(OrderStatusEnum.NEW_ORDER.value()); // 待确认
        orderEntity.setOrderType(dto.getOrderType());
        orderEntity.setOrderSource(0); // 官方

        // 设置价格信息
        orderEntity.setEvaluatePrice(evaluateLog.getEvaluatePrice());
        orderEntity.setQualityPrice(BigDecimal.ZERO);
        orderEntity.setBonusPrice(BigDecimal.ZERO);
        orderEntity.setOrderPrice(evaluateLog.getEvaluatePrice());
        orderEntity.setCompletePrice(BigDecimal.ZERO);
        
        // 设置支付状态
        orderEntity.setPayType(0);
        orderEntity.setPayStatus(0); // 未支付
        orderEntity.setPrepaidStatus(0);
        orderEntity.setLogisticsStatus(-1); // 无物流
        
        // 设置时间信息
        Date now = Dates.getTimeNow();
        orderEntity.setCreateTime(now);
        orderEntity.setUpdateTime(now);
        orderEntity.setAppointStartTime(dto.getAppointStartTime());
        orderEntity.setAppointEndTime(dto.getAppointEndTime());


        // 设置渠道和平台信息
        orderEntity.setPartnerId(partnerEntity.getPartnerId());
        orderEntity.setPartnerName(partnerEntity.getPartnerName());
        orderEntity.setPlatform(platform);
        orderEntity.setChannel(Strings.defaultString(channel, Strings.EMPTY));
        
        // 设置备注
        orderEntity.setOrderRemark(dto.getRemark());
        orderEntity.setAppId("");
        
        // 4. 保存订单
        orderRepository.insertSelective(orderEntity);
        Long orderId = orderEntity.getOrderId();

        log.info("订单创建成功，订单ID：{}，订单号：{}", orderId, orderNo);
        
        // 5. 保存订单产品信息
        createOrderProduct(orderId,evaluateLog);
        
        // 6. 保存订单地址信息
        createOrderAddress(orderId, userId, dto);
        
        // 7. 保存订单扩展信息
        createOrderExtend(orderId, dto);

        // 8. 保存用户收款方式
        createUserPaymentMethod(userId, dto);

        return orderEntity;
    }

    /**
     * 生成订单号
     */
    private String generateOrderNo() {
        String timestamp = Dates.format(Dates.getTimeNow(), "yyyyMMddHHmmss");
        String random = String.format("%04d", (int)(Math.random() * 10000));
        return "C" + timestamp + random;
    }

    /**
     * 获取渠道信息
     */
    private PartnerEntity getPartnerInfo(Long partnerId) {
        if (Longs.isNullOrZero(partnerId)) {
            throw Ex.business("渠道ID不能为空");
        }
        final Long partnerIdValue = Long.valueOf(partnerId);
        PartnerEntity partnerEntity = partnerApiService.getPartnerInfo(partnerIdValue);
        if (Objects.isNull(partnerEntity)) {
            throw Ex.business("渠道信息不存在");
        }
        return partnerEntity;
    }

    /**
     * 保存用户收款方式
     */
    private void createUserPaymentMethod(Long userId, OrderSubmitApiDTO dto) {
        final AccountInfoApiDTO accountApiDTO = dto.getAccountInfo();
        if (Objects.nonNull(accountApiDTO)) {
            final String accountName = accountApiDTO.getAccountName();
            final String accountNumber = accountApiDTO.getAccountNumber();
            userPaymentMethodApiService.createUserPayment(userId, accountName, accountNumber);
        } else {
            log.warn("用户收款方式信息为空，跳过保存");
        }
    }

    /**
     * 创建订单产品信息
     */
    private void createOrderProduct(Long orderId, EvaluateLogEntity evaluateLog) {
        OrderProductEntity orderProductEntity = Beans.copy(evaluateLog, OrderProductEntity.class);
        orderProductEntity.setOrderId(orderId);
        orderProductEntity.setCreateTime(Dates.getTimeNow());
        orderProductEntity.setUpdateTime(Dates.getTimeNow());
        
        orderProductEntity.setQualityPrice(BigDecimal.ZERO);
        
        orderProductRepository.insertSelective(orderProductEntity);
        log.debug("订单产品信息创建成功，订单ID：{}", orderId);
    }
    
    /**
     * 创建订单地址信息
     */
    private void createOrderAddress(Long orderId, Long userId, OrderSubmitApiDTO dto) {
        final OrderAddressApiDTO orderAddressApiDTO = dto.getAddressInfo();
        final Long districtCode = orderAddressApiDTO.getDistrictCode();
        RegionEntity regionEntity = regionService.getRegionByCode(districtCode);
        if (Objects.isNull(regionEntity)) {
            throw Ex.business("区域信息不存在，区县编码：{}" , districtCode);
        }
        OrderAddressEntity orderAddressEntity = Beans.copy(regionEntity, OrderAddressEntity.class);
        orderAddressEntity.setOrderId(orderId);
        orderAddressEntity.setUserId(userId);
        orderAddressEntity.setUserName(orderAddressApiDTO.getUserName());
        orderAddressEntity.setUserPhone(orderAddressApiDTO.getUserPhone());
        orderAddressEntity.setAddress(orderAddressApiDTO.getAddress());
        orderAddressEntity.setCreateTime(Dates.getTimeNow());
        orderAddressEntity.setUpdateTime(Dates.getTimeNow());
        orderAddressRepository.insertSelective(orderAddressEntity);
    }
    
    /**
     * 创建订单扩展信息
     */
    private void createOrderExtend(Long orderId, OrderSubmitApiDTO dto) {
        final OrderExtendApiDTO orderExtendApiDTO = dto.getExtendInfo();
        Long bonusId = Numbers.LONG_ZERO;
        BigDecimal bonusPrice = BigDecimal.ZERO;
        final String openId = orderExtendApiDTO.getOpenId();
        if (Objects.nonNull(orderExtendApiDTO)) {
            bonusId = orderExtendApiDTO.getBonusId();
            bonusPrice = orderExtendApiDTO.getBonusPrice();
        }
        OrderExtendEntity orderExtendEntity = new OrderExtendEntity();
        orderExtendEntity.setOrderId(orderId);
        orderExtendEntity.setBonusId(bonusId);
        orderExtendEntity.setBonus(bonusPrice);
        orderExtendEntity.setOpenId(openId);
        orderExtendEntity.setCreateTime(Dates.getTimeNow());
        orderExtendEntity.setUpdateTime(Dates.getTimeNow());
        orderExtendRepository.insertSelective(orderExtendEntity);

        
        log.info("订单扩展信息创建成功，订单ID：{}", orderId);
    }

    /**
     * 订单创建后处理
     */
    private void handleOrderAfter(OrderEntity orderEntity, OrderSubmitApiDTO dto) {

        // 1. 给用户发送短信通知
        handleSendUserNotify(orderEntity);
        // 2. 处理合作商推广标签
        handlePartnerPromoteLabel(orderEntity, dto);
        // 3. 给速回收同步订单信息
        handleSyncSuhuishou(orderEntity);
        // 4. 预约快递延时10s
        handleExpressReservation(orderEntity);
        // 5. 处理红包验证（仅邮寄订单）
        handleBonusVerification(orderEntity, dto);
        //6.发送支付宝消息
        handleAlipaySubscribeMessage(orderEntity);
        
        log.info("订单后续处理开始，订单ID：{}", orderEntity.getOrderId());
    }

    /**
     * 给用户发送短信通知
     */
    private void handleSendUserNotify(OrderEntity orderEntity) {
        final Long orderId = orderEntity.getOrderId();
        notifyMessageSender.sendSmsNotifyMessage(orderId);
    }

    /**
     * 处理红包验证（仅邮寄订单）
     */
    private void handleBonusVerification(OrderEntity orderEntity, OrderSubmitApiDTO dto) {
        if (!Objects.equals(orderEntity.getOrderType(), OrderTypeEnum.EXPRESS_RECYCLE.value())) {
            log.info("非邮寄订单，跳过红包验证，订单ID：{}", orderEntity.getOrderId());
            return;
        }
        
        final OrderExtendApiDTO orderExtendApiDTO = dto.getExtendInfo();
        if (Objects.isNull(orderExtendApiDTO)) {
            log.info("订单扩展信息为空，跳过红包验证，订单ID：{}", orderEntity.getOrderId());
            return;
        }
        
        final Long bonusId = orderExtendApiDTO.getBonusId();
        if (Longs.notNullAndZero(bonusId)) {
            final Long orderId = orderEntity.getOrderId();
            rabbitMQUtil.sendMessage(RabbitMqQueueEnum.BONUS_VERIFICATION.getQueueName(), orderId);
            log.info("发送红包验证消息，订单ID：{}，红包ID：{}", orderId, bonusId);
        }
    }


    /**
     * 处理合作商推广标签
     * @param orderEntity
     * @param dto
     */
    private void handlePartnerPromoteLabel(OrderEntity orderEntity, OrderSubmitApiDTO dto) {
        final String promoteLabel = dto.getChannel();
        final Long orderId = orderEntity.getOrderId();
        if (Strings.isEmpty(promoteLabel)) {
            return;
        }
        //调用队列
        PromoteMqDTO promoteMqDTO = new PromoteMqDTO();
        promoteMqDTO.setOrderId(orderId);
        promoteMqDTO.setPromoteLabel(promoteLabel);
        rabbitMQUtil.sendMessage(RabbitMqQueueEnum.PROMOTE_LABEL.getQueueName(), promoteMqDTO);
    }

    /**
     * 给速回收同步订单信息
     */
    private void handleSyncSuhuishou(OrderEntity orderEntity) {
        if (DevOption.isDevModel()){
            log.info("开发模式下不发送速回收订单同步消息，订单ID：{}", orderEntity.getOrderId());
//            return;
        }
        final Long orderId = orderEntity.getOrderId();
        rabbitMQUtil.sendDelayMessage(RabbitMqQueueEnum.SUHUISHOU_ORDER_CREATE.getQueueName(), orderId,5L,TimeUnit.SECONDS);
    }

    /**
     * 处理快递预约（延时10秒）
     */
    private void handleExpressReservation(OrderEntity orderEntity) {
        try {
            final Long orderId = orderEntity.getOrderId();
            
            log.info("发送快递预约延时消息，订单ID: {}", orderId);
            
            // 延时20秒发送快递预约消息
            rabbitMQUtil.sendDelayMessage(RabbitMqQueueEnum.EXPRESS_RESERVATION.getQueueName(), orderId,20L,TimeUnit.SECONDS);

            log.info("快递预约延时消息发送成功，订单ID: {}", orderId);
        } catch (Exception e) {
            log.error("发送快递预约延时消息异常，订单ID: {}, 错误信息: {}", orderEntity.getOrderId(), e.getMessage(), e);
            // 不抛出异常，避免影响订单创建流程
        }
    }



    /**
     * 处理支付宝订阅消息
     */
    private void handleAlipaySubscribeMessage(OrderEntity orderEntity) {
        try {
            final Long orderId = orderEntity.getOrderId();
            notifyMessageSender.sendAlipaySubscribeMessage(orderId, orderEntity.getPlatform(), "ORDER_SUCCESS");
        } catch (Exception e) {
            log.error("发送支付宝订阅消息异常，订单ID: {}, 错误信息: {}", orderEntity.getOrderId(), e.getMessage(), e);
            // 不抛出异常，避免影响订单创建流程
        }
    }
}
